package algorithms.utis;

import algorithms.a04heap.IndexMaxHeap;
import com.google.common.base.Preconditions;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Method;

public class SortTestHelper {

    // 打印arr数组的所有内容
    public static String printArray(Object arr[]) {

        String content = "";
        for (int i = 0; i < arr.length; i++) {
            content += arr[i] + " ";
        }
        return content;
    }

    /**
     * 生成随机数组
     *
     * @param n
     * @param rangeL
     * @param rangeR
     * @date: 2018-02-03 下午 10:47
     * @author: 王昊然
     */
    public static Integer[] generateRandomArray(int n, int rangeL, int rangeR) {

        Preconditions.checkArgument(rangeL < rangeR, "参数不正确，rangeL需要小于rangeR");

        Integer[] arr = new Integer[n];

        for (int i = 0; i < n; i++)
            arr[i] = RandomUtils.nextInt(rangeL, rangeR);

        return arr;
    }

    // 生成一个近乎有序的数组
    // 首先生成一个含有[0...n-1]的完全有序数组, 之后随机交换swapTimes对数据
    // swapTimes定义了数组的无序程度:
    // swapTimes == 0 时, 数组完全有序
    // swapTimes 越大, 数组越趋向于无序
    public static Integer[] generateNearlyOrderedArray(int n, int swapTimes) {

        Integer[] arr = new Integer[n];
        for (int i = 0; i < n; i++)
            arr[i] = new Integer(i);

        for (int i = 0; i < swapTimes; i++) {
            int a = (int) (Math.random() * n);
            int b = (int) (Math.random() * n);
            int t = arr[a];
            arr[a] = arr[b];
            arr[b] = t;
        }

        return arr;
    }


    // 判断arr数组是否有序
    public static boolean isSorted(Comparable[] arr) {

        for (int i = 0; i < arr.length - 1; i++)
            if (arr[i].compareTo(arr[i + 1]) > 0)
                return false;
        return true;
    }

    // 判断arr数组是否符合最大堆格式
    public static boolean isMaxHeapData(Comparable[] arr) {

        for (int i = arr.length-1; i >1; i--)
            if (arr[i].compareTo(arr[i/2]) > 0)
                return false;
        return true;
    }


    // 测试sortClassName所对应的排序算法排序arr数组所得到结果的正确性和算法运行时间
    public static void testSort(Class c, Comparable[] arr, String methodName) {

        try {
            // 通过排序函数的Class对象获得排序方法
            if (StringUtils.isBlank(methodName)) {
                methodName = "sort";//默认方法名
            }
            Method sortMethod = c.getMethod(methodName, new Class[]{Comparable[].class});
            // 排序参数只有一个，是可比较数组arr
            Object[] params = new Object[]{arr};

            long startTime = System.currentTimeMillis();
            // 调用排序函数
            sortMethod.invoke(null, params);
            long endTime = System.currentTimeMillis();

            //assert isSorted( arr );
            Preconditions.checkArgument(isSorted(arr), c.getSimpleName() + "类排序方法有问题，未按照从小到大排序！\\t\\n排序后的数组为：｛｝", printArray(arr));
            System.out.println(c.getSimpleName() + "-" + sortMethod.getName() + " : " + (endTime - startTime) + "ms");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void testSort(Class c, Comparable[] arr) {
        testSort(c, arr, null);
    }


}
